package com.atguigu.spring;

import com.atguigu.spring.aop.AsyncAnnotationExample;
import com.atguigu.spring.aop.HelloService;
import com.atguigu.spring.bean.Cat;
import com.atguigu.spring.bean.Hello;
import com.atguigu.spring.bean.Person;
import com.atguigu.spring.config.MainConfig;
import com.atguigu.spring.listener.A;
import com.atguigu.spring.listener.AppEventPublisher;
import com.atguigu.spring.listener.ChangeEvent;
import com.atguigu.spring.listener.MessageEvent;
import com.atguigu.spring.service.CashService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.math.BigDecimal;
import java.util.concurrent.CompletableFuture;

/**
 * @author mi
 * @time 2021/3/7 8:46
 */
public class AnnotationTest {
	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		//Lookup注解 测试
//		testLookupAnnotation(context);

		//AOP,原理测试
//		testAOP(context);

		//tx 事务测试
//		testTX(context);

		//定义事件发布
//		testEventPublish(context);
		//测试属性填充
//		testAutowiredAnnotation(context);

		// 测试factoryBean的创建与com.atguigu.spring.bean.HelloFactory.getObject() 创建hello组件
//		testFactoryBean(context);
		//
		testAsync(context);
	}

	private static void testFactoryBean(AnnotationConfigApplicationContext context) {
		Hello bean = context.getBean(Hello.class);
		Hello bea2 = context.getBean(Hello.class);
		System.out.println(bean == bea2); //还是单例
	}

	private static void testAutowiredAnnotation(AnnotationConfigApplicationContext context) {
		Person person = context.getBean(Person.class);
		System.out.println(person);
	}


	//Lookup注解 测试
	private static void testLookupAnnotation(AnnotationConfigApplicationContext context) {
		Person person1 = context.getBean(Person.class);
		Cat cat1 = person1.getCat();

		Person person2 = context.getBean(Person.class);
		Cat cat2 = person2.getCat();

		System.out.println(cat1==cat2);
	}



	//AOP,原理测试
	private static void testAOP(AnnotationConfigApplicationContext context) {
		//AOP,原理测试
		HelloService helloService = context.getBean(HelloService.class);

		//代理对象来调用方法
		helloService.sayHello("zhangsan");
	}


	//AOP-Async,原理测试
	private static void testAsync(AnnotationConfigApplicationContext context) {
		//Async 示例代理对象
		AsyncAnnotationExample example = context.getBean(AsyncAnnotationExample.class);

		//代理对象来调用方法
		CompletableFuture<String> completableFuture = example.doSomething();
		System.out.println(completableFuture.join());
	}

	// 没有引入数据源，重点是观察到 ，事务拦截器其实就是一个 -- "环绕通知"
	private static void testTX(AnnotationConfigApplicationContext context) {
//		//AOP,原理测试
//		CashService cashService = context.getBean(CashService.class);
//
//		//jdk代理对象来调用方法
//		cashService.addUserBalanceAndUser("xm",new BigDecimal(10));


		//CIGLIB,原理测试
		HelloService helloService = context.getBean(HelloService.class);

		//代理对象来调用方法
		helloService.sayHello("zhangsan");
	}



	private static void testEventPublish(AnnotationConfigApplicationContext context){
		//容器本身就实现了ApplicationEventPublisher 接口，可以发布事件
		context.publishEvent(new Object());

		//自定义事件发布器
		AppEventPublisher eventPublisher = context.getBean(AppEventPublisher.class);
		/**
		 * 会被包装成 PayloadApplicationEvent，本质还是ApplicationEvent
		 */
		eventPublisher.publish(new A());
		eventPublisher.publish(new MessageEvent("hello，你好"));
		eventPublisher.publish(new ChangeEvent(eventPublisher,"sending..."));
	}
}
